#include "interface_fil.h"
#include <QDebug>
#include <cstring>
interface_fil::interface_fil(QWidget* parent) : interface_mdle(parent)
{
    table->setItem(1-1, 1-1, new QTableWidgetItem(QString("itf_type")));
    table->setItem(1-1, 2-1, new QTableWidgetItem(QString("fil")));
    // --------------------------------------------
    // 连接逻辑信号到IO上，统一到父类，方便器件访问
    connect(this,&interface_fil::io_send_fil_trig,
            this,&interface_mdle::itf_out_tx); //主机发送逻辑
    connect(this,&interface_mdle::itf_in_rx,
            this,&interface_fil::io_recv_fil_slot); //从机接收逻辑
    connect(this,&interface_mdle::itf_out_rx,
            this,&interface_fil::io_recv_fil_slot); //主机接收逻辑
    /* master == out
     * slaver == in
     * IO代表主机和从机都可以使用，后续为了方便区分，就禁止这样
     */
}
// =====================================================
// 从机接收逻辑（通用逻辑，转化为给器件内部的信号）
void interface_fil::io_recv_fil_slot( QVariantList & itfs)//itf_fil fil) //
{
    if(!itfs.at(0).canConvert<itf_fil>()) //类型检查,类型不对不执行，只检查一个数据包，后续协议如果拓展，可以同时发送多个包
    {
        QDEBUG << "slaver data, and match status is " << false;
        return;
    }

    recv_fil = itfs.at(0).value<itf_fil>(); //缓存接收的结构体方便后续使用，因为信号是器件先收到，所以不需要再返回给器件
    emit recv_fil_trig(recv_fil); //IO就绪，由器件决定响应的逻辑
}
// =====================================================
// 主机发送逻辑
void interface_fil::master_send_list()
{
    send_fil.id = 0x0;
    send_fil.size = 0x0; //无文件内容，纯指令
    int len = sizeof(send_fil.addr) / sizeof(quint32); //获取目录级数
    for(int i = 0; i < len; i++)
    {
        send_fil.addr[i] = 0x0;
    }
    //| strcpy(send_fil.type,"list"); //确保长度为4字节,该方式不保险
    memcpy(send_fil.type,"list",4);
    send_fil.data.clear(); //无数据负载
    qDebug() << __FILE__ << __LINE__ << "m_fil size is:" << send_fil.size;

    //预设的指令直接触发
    QVariantList list;
    list << QVariant::fromValue(send_fil);
    emit io_send_fil_trig(list);
}
// --------------------------------------------
// 从机发送逻辑
void interface_fil::slaver_send_list(QStringList title)
{
    send_fil.id = 0x0;
    send_fil.size = title.count() * sizeof(quint32); //回复目录结构
    int len = sizeof(send_fil.addr) / sizeof(quint32); //获取目录级数
    for(int i = 0; i < len; i++)
    {
        send_fil.addr[i] = 0x0;
    }
    //| strcpy(send_fil.type,"list"); //确保长度为4字节,确认该方式会导致程序崩溃
    memcpy(send_fil.type,"list",4);
    send_fil.data.clear(); //重新加载数据
    bool ok; //
    QString str_data = title.join(""); // 直接将提取的所有文件头按照顺序缓存，然后直接转化为字节序发送出去
    for(int i = 0; i < str_data.length();i=i+2) //2字节转化一个16进制数
    {
        quint8 byte_hex = str_data.midRef(i,2).toUInt(&ok,16);
        if(!ok) //字符串错误
        {
            QDEBUG << "string is not hex";
            return ;
        }
        send_fil.data.append(byte_hex);
    }
    QDEBUG << title.join("").toUtf8()  << "m_fil size is:" << send_fil.size;

    //预设的指令直接触发
    QVariantList list;
    list << QVariant::fromValue(send_fil);
    emit itf_in_tx(list); //发送从机的发送信号
}
// --------------------------------------------
// 主机发送逻辑
/* 按照目录结构的特点，应当存储如下的内容：
 * 将结构体类型前面的信息全部缓存下来，也就是一个文件48字节
 *
 */
QStringList interface_fil::master_recv_list()
{
    QStringList md_title = {}; //获取md格式的目录
    QString type = QString::fromUtf8(recv_fil.type, 4); // 只处理前5个字符

    if(type == "list") //检查一下格式是否正确
    {
        int dir_len = sizeof(recv_fil.addr) / sizeof(quint32); //获取目录级数
        int info_len = 4 * 2 + sizeof(recv_fil.addr); //缓存信息的长度
        for(int i = 0; i < int(sizeof(recv_fil.data)); i = i + info_len)
        {
            QString title;
            int dir_len_valid = 0;
            //获取目录结构
            QString raw_title;
            for(int j = 0; j < dir_len; j++)
            {
                raw_title = recv_fil.data.mid(i*info_len+j*4+8, sizeof(quint32)).toHex();
                qDebug() << "raw_title" << raw_title;
                if(raw_title == 0x0) //目录结束，不再生成
                {
                    dir_len_valid = j;
                    break;
                }
                title.clear();
                title.fill('#',j+1);
                title += " ";
                title += raw_title;
                md_title.append(title);
                dir_len_valid = j;
            }
            //额外执行一次，将文件内容挂载目录下
                title.clear();
                title.fill('#',dir_len_valid+1);
                title += " ";
                raw_title = recv_fil.data.mid(i*info_len+0, sizeof(quint32)).toHex();
                title += raw_title; //加载文件名
                raw_title = recv_fil.data.mid(i*info_len+4, sizeof(quint32)).toHex();
                title += "+:"; //加载数据长度
                title += raw_title; //加载数据长度
                md_title.append(title);
                QDEBUG << recv_fil.data.mid(i*info_len+0, info_len ).toHex();
        }

    }
    return md_title; //解析出对应的目录
}


